package com.ruoyi.web.core.tool;

import com.ruoyi.business.goods.domain.vo.JbCropVarietyVo;

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.Function;

/**
 * 实体类处理工具
 *
 * @author Jyl
 */
public class ColumnUtil
{

    public static void main(String[] args)
    {
        System.err.println(ColumnUtil.M(JbCropVarietyVo::getCreateName));
    }

    /**
     * 获取 方法名
     *
     * @param fn
     * @param <T>
     * @return
     */
    public final static <T> String M(SFunction<T, ?> fn)
    {
        return getMethodName(fn);
    }

    /**
     * 获取 字段名
     *
     * @param fn
     * @param <T>
     * @return
     */
    public final static <T> String F(SFunction<T, ?> fn)
    {
        return getFieldName(fn);
    }

    public interface SFunction<T, R> extends Function<T, R>, Serializable
    {

    }

    protected static <T> String getMethodName(SFunction<T, ?> fn)
    {
        SerializedLambda serializedLambda = getSerializedLambda(fn);
        String methodName = serializedLambda.getImplMethodName();
        return methodName;
    }

    protected static <T> String getFieldName(SFunction<T, ?> fn)
    {
        SerializedLambda serializedLambda = getSerializedLambda(fn);
        String methodName = serializedLambda.getImplMethodName();
        String field = methodName.substring(3);
        field = field.substring(0, 1).toLowerCase() + field.substring(1);
        return field;
    }

    private static <T> SerializedLambda getSerializedLambda(SFunction<T, ?> fn)
    {
        Method writeReplaceMethod;
        try
        {
            writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace");
        } catch (NoSuchMethodException e)
        {
            throw new RuntimeException(e);
        }
        boolean accessible = writeReplaceMethod.isAccessible();
        writeReplaceMethod.setAccessible(true);
        SerializedLambda serializedLambda = null;
        try
        {
            serializedLambda = (SerializedLambda) writeReplaceMethod.invoke(fn);
        } catch (IllegalAccessException e)
        {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e)
        {
            throw new RuntimeException(e);
        }
        writeReplaceMethod.setAccessible(accessible);
        return serializedLambda;
    }

}
